﻿define([
    'dojo/_base/declare',
    'esri/dijit/PopupTemplate',
    'esri/symbols/PictureMarkerSymbol',
    'esri/symbols/SimpleMarkerSymbol',
    'esri/SpatialReference',
    'geomap/plugins/layers/ClusterLayer',
], function (
    declare,
    PopupTemplate,
    PictureMarkerSymbol,
    SimpleMarkerSymbol,
    SpatialReference,
    BaseClusterLayer
) {
    var ClusterLayer = declare([BaseClusterLayer], {
        constructor: function (options) {
            this._sr = options.sr
                ? new SpatialReference({ wkid: 4326 })
                : typeof options.sr == 'number'
                ? new SpatialReference({ wkid: options.sr })
                : new SpatialReference({ wkt: options.sr });
        },
        _setLayer: function (val) {
            this._layer = val;
        },
        _getLayer: function () {
            return this._layer;
        },
        setData: function (mapUtils, layer) {
            var me = this;
            me.clear();
            me._setLayer(layer);
            me.mapUtils = mapUtils;
            me._map = mapUtils.getMap();

            me.__getSymbol = mapUtils.getSymbol.bind(mapUtils);
            var options = Object.assign({}, layer.layer);
            me.options = options;
            me._clusterTolerance = options.distance || 50;

            me._clusters = [];

            me._clusterLabelColor = options.labelColor || [120, 120, 120, 255];

            me._clusterLabelOffset = options.hasOwnProperty('labelOffset')
                ? options.labelOffset
                : -5;

            me._singles = [];
            me._showSingles = options.hasOwnProperty('showSingles') ? options.showSingles : true;

            // me._singleTemplate = options.singleTemplate || new PopupTemplate({"title": "", "description": "{*}"});
            /*聚类点位超过这个数据，点击不散开*/
            me._maxSingles = options.maxSingles || 300;
            /*数据源超过这个数据，才开始聚类*/
            me._thresholdValue = options.thresholdValue || 0;
            /*地图比例尺小于这个数据，不再聚类，全部散开*/
            me._clusterUpperLimitScale = options.clusterUpperLimitScale || 0;
            /*地图级别大于这个数据，不再聚类，全部散开*/
            me._clusterUpperLimitLevel = options.clusterUpperLimitLevel || 0;

            me._webmap = options.hasOwnProperty('webmap') ? options.webmap : false;

            me._sr = me.spatialReference;

            me._zoomEnd = null;

            me._renderSingleCallback = options.renderSingleCallback;
            me.lngFieldName = lngFieldName = options.lngFieldName || 'x';
            me.latFieldName = latFieldName = options.latFieldName || 'y';
            me._minScale = options.minScale || 0;
            me._maxScale = options.maxScale || 0;

            me._clusterResolution = this._map.extent.getWidth() / this._map.width;

            me._clickEvent = options.onClick || options.clickEvent;
            me._mouseOverEvent = options.onMouseOver || options.mouseOverEvent;
            me._mouseOutEvent = options.onMouseOut || options.mouseOutEvent;

            if (options.layerUrl) {
                var where = options.where || '1=1';
                mapUtils.queryTask(mapUtils, options.layerUrl, {
                    where: where,
                    callback: function (e) {
                        options.data = e.result;
                        if (
                            Object.prototype.toString.call(options.data) != '[object Array]' ||
                            options.data.length < 1
                        ) {
                            console.log('聚类图层缺少数据源！');
                            if (typeof options.callback == 'function') {
                                options.callback(layer);
                            }
                            return;
                        }
                        me.calClusterData(mapUtils, options);
                        me.setLabel(mapUtils, options);
                        if (options.clusterRenderer) {
                            me.__setRenderer(mapUtils, options.clusterRenderer, layer);
                        } else {
                            me.setClusterSymList(mapUtils, layer);
                        }
                    },
                });
            } else {
                if (
                    Object.prototype.toString.call(options.data) != '[object Array]' ||
                    options.data.length < 1
                ) {
                    console.log('聚类图层缺少数据源！');
                    if (typeof options.callback == 'function') {
                        options.callback(layer);
                    }
                    return;
                }
                // TODO 地理坐标和平面坐标转换
                if (this._sr.isWebMercator()) {
                    mapUtils.geographicToWebMercator(
                        mapUtils,
                        options.data,
                        Object.assign(options, {
                            callback: function (data) {
                                options.data = data;
                                _srCallback();
                            },
                        })
                    );
                } else {
                    _srCallback();
                }
            }

            function _srCallback() {
                me.calClusterData(mapUtils, options);
                me.setLabel(mapUtils, options);
                if (options.clusterRenderer) {
                    me.__setRenderer(mapUtils, options.clusterRenderer, layer);
                } else {
                    me.setClusterSymList(mapUtils, layer);
                }
            }
        },
        isWgs84ToWebMercator: function () {
            var me = this;

            if (me.spatialReference.wkid == 4326 && this._map.spatialReference.wkid == 102100) {
                return true;
            }
            return false;
        },
        calClusterData: function (mapUtils, options) {
            var me = this;
            me._clusterData = [];
            var lngLatArray = mapUtils.toLngLatArray(mapUtils, options.data, options);
            for (var i = 0; i < lngLatArray.length; i++) {
                var item = lngLatArray[i];
                if (item.x > 0 && item.y > 0) {
                    me._clusterData.push(item);
                }
            }
        },
        setLabel: function (mapUtils, options) {
            var me = this;
            if (options.labelOptions) {
                me.labelOptions = Object.assign(
                    {
                        textField: 'name',
                        ptThreshold: 0, //当前窗口的点位少于这个最大值时，标签强制展示
                        showLabels: 1, //1:根据比例尺展示，2：强制展示，0：强制不展示
                        scaleInfo: {
                            maxScale: 0, // 1000000,
                            minScale: 0,
                        },
                        labelSymbol: {
                            labelClass: 'labelInfo',
                            labelStyle: { offsety: 18, offsetx: 0, position: 'top' },
                        },
                    },
                    options.labelOptions
                );
                me._showLabels(mapUtils, options);
            }
        },
        setClusterSymList: function (mapUtils, layer) {
            var me = this;
            var options = layer.layer || {};
            var clusterSymList = [
                {
                    begin: 1,
                    end: 2,
                    symbol: {
                        type: 'esriSMS',
                        style: 'esriSMSCircle',
                        color: [0, 255, 255, 250],
                        size: 12,
                        outline: {
                            color: [0, 255, 255],
                            type: 'esriSLS',
                            style: 'esriSLSSolid',
                            width: 1,
                        },
                    },
                },
                {
                    begin: 2,
                    end: 100,
                    symbol: {
                        type: 'esriSMS',
                        style: 'esriSMSCircle',
                        color: [45, 140, 240, 200],
                        size: 25,
                        outline: {
                            color: [45, 140, 240],
                            type: 'esriSLS',
                            style: 'esriSLSSolid',
                            width: 1,
                        },
                    },
                },
                {
                    begin: 100,
                    end: 500,
                    symbol: {
                        type: 'esriSMS',
                        style: 'esriSMSCircle',
                        color: [45, 140, 240, 200],
                        size: 30,
                        outline: {
                            color: [45, 140, 240],
                            type: 'esriSLS',
                            style: 'esriSLSSolid',
                            width: 1,
                        },
                    },
                },
                {
                    begin: 500,
                    end: 1000,
                    symbol: {
                        type: 'esriSMS',
                        style: 'esriSMSCircle',
                        color: [45, 140, 240, 200],
                        size: 35,
                        outline: {
                            color: [45, 140, 240],
                            type: 'esriSLS',
                            style: 'esriSLSSolid',
                            width: 1,
                        },
                    },
                },
                {
                    begin: 1000,
                    end: Number.MAX_VALUE,
                    symbol: {
                        type: 'esriSMS',
                        style: 'esriSMSCircle',
                        color: [45, 140, 240, 200],
                        size: 40,
                        outline: {
                            color: [45, 140, 240],
                            type: 'esriSLS',
                            style: 'esriSLSSolid',
                            width: 1,
                        },
                    },
                },
            ];
            this._clusterSymList =
                options.clusterSymList && options.clusterSymList.length > 0
                    ? options.clusterSymList
                    : clusterSymList;

            for (let i = 0, j = this._clusterSymList.length; i < j; i++) {
                var item = me._clusterSymList[i];
                var symbolFieldName = options.clusterSymbolFieldName || 'symbol';
                let symbol;
                if (item[symbolFieldName].type == 'esriSMS') {
                    symbol = new SimpleMarkerSymbol(item.symbol);
                    item.symbol = symbol;
                } else if (item[symbolFieldName].type == 'esriPMS') {
                    symbol = new PictureMarkerSymbol(item.symbol);
                    item.symbol = symbol;
                }
                // mapUtils.getSymbol(mapUtils, item[symbolFieldName], function (symbol) {
                // item.symbol = symbol;
                if (i == 0) {
                    me._singleSym = symbol;
                }
                if (i == j - 1) {
                    me.__refresh();

                    if (typeof options.callback == 'function') {
                        options.callback(layer);
                    }
                }
                //});
            }
        },
        __setRenderer: function (mapUtils, rendererOptions, layer) {
            var me = this;
            var options = layer.layer || {};

            var renderer = null;

            switch (rendererOptions.type) {
                case mapUtils.Enum.RenderType.SimpleRenderer:
                    renderer = mapUtils.getSimpleRenderer(mapUtils, rendererOptions.symbol);
                    break;
                case mapUtils.Enum.RenderType.UniqueValueRenderer:
                    renderer = mapUtils.getUniqueValueRenderer(
                        mapUtils,
                        rendererOptions.symbol || rendererOptions
                    );
                    break;
                case mapUtils.Enum.RenderType.ClassBreaksRenderer:
                    renderer = mapUtils.getClassBreaksRenderer(
                        mapUtils,
                        rendererOptions.symbol || rendererOptions
                    );
                    break;
            }
            me.setRenderer(renderer);
            me.__refresh();
            if (typeof options.callback == 'function') {
                options.callback(layer);
            }
        },
    });
    return ClusterLayer;
});
